Skip to content

fix(acp-server): surface provider errors on session/prompt - #3161

Open
jangjoe wants to merge 2 commits into
MoonshotAI:mainfrom
jangjoe:fix/surface-provider-errors
Open

fix(acp-server): surface provider errors on session/prompt#3161
jangjoe wants to merge 2 commits into
MoonshotAI:mainfrom
jangjoe:fix/surface-provider-errors

Conversation

@jangjoe

@jangjoe jangjoe commented Aug 21, 2026

Copy link
Copy Markdown

Resolve #3107

session/prompt used to silently resolve with {stopReason: 'end_turn'}
when the model provider returned a transport / status failure
(rate limit, overload, 5xx, connection loss, etc.). The engine already
classifies these as born-coded Error2 instances with codes like
provider.api_error / provider.overloaded /
provider.connection_error / context.overflow and surfaces them
on turn.ended{ reason: 'failed' }, but the ACP layer only knew how
to map auth errors — every other failure was swallowed into end_turn
and clients had no way to tell the model service was unavailable.

Change

Add isProviderError() in packages/acp-server/src/events-map.ts
(sibling to isAuthError()) and a third branch in both
AcpSession.onTurnEnded and mapPromptLaunchError: provider /
context failures now reject with
RequestError.internalError({ code, message }, "model provider reported an error"). The engine's full text rides in the JSON-RPC
data payload so clients can log it; the wire message stays generic
to keep provider-supplied PII out of every error toast.

  • Auth failures keep their existing auth_required mapping.
  • Content-filter failures (provider.filtered) keep the legacy
    refusal mapping in turnEndReasonToStopReason and fall through
    to the fixed generic message at launch (where no turn exists yet to
    attach a refusal to).

The scripted provider helper gains mockNextProviderError(code, message)
so end-to-end tests can throw a coded provider error without going
through the network layer.

Test plan

  • packages/acp-server/test/events-map.test.ts — new unit tests for
    isAuthError / isProviderError / turnEndReasonToStopReason,
    covering every code in each set plus the cross-set negatives
    (provider.filtered must not match isProviderError).
  • packages/acp-server/test/e2e-turn.test.tsmapPromptLaunchError
    unit tests for provider.api_error / context.overflow /
    provider.filtered (legacy) and a scripted end-to-end test that
    throws a coded provider error mid-turn and asserts the prompt
    rejects as internalError carrying the engine message in data.

`session/prompt` used to silently resolve with `{stopReason: 'end_turn'}`
when the model provider returned a transport / status failure
(rate limit, overload, 5xx, connection loss, etc.). The engine already
classifies these as born-coded `Error2` instances with codes like
`provider.api_error` / `provider.overloaded` /
`provider.connection_error` / `context.overflow` and surfaces them
on `turn.ended{ reason: 'failed' }`, but the ACP layer only knew how to
map auth errors — every other failure was swallowed into `end_turn`
and clients had no way to tell the model service was unavailable.

Add `isProviderError()` in events-map.ts (sibling to `isAuthError()`)
and a third branch in both `AcpSession.onTurnEnded` and
`mapPromptLaunchError`: provider / context failures now reject with
`RequestError.internalError({ code, message }, "model provider
reported an error")`. The engine's full text rides in the JSON-RPC
`data` payload so clients can log it; the wire message stays generic
to keep provider-supplied PII out of every error toast. Auth failures
keep their existing `auth_required` mapping; content-filter failures
keep the legacy `refusal` mapping in `turnEndReasonToStopReason`.

The scripted provider helper gains `mockNextProviderError(code, message)`
so end-to-end tests can throw a coded provider error without going
through the network layer.

Resolve MoonshotAI#3107
@changeset-bot

changeset-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f06428b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Signed-off-by: Jang Joe <jangjoe@qq.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f06428b836

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +235 to +236
mockNextProviderError: (code, message) => {
queue.push({ throwError: new Error2(code, message) });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the requested scripted error code

When mockNextProviderError is called with anything other than provider.api_error, the queued Error2 is caught by the helper's existing requester.generate catch and reduced to an llm.failed.remote event with kind: 'unknown'; errorFromLlmMessage then reconstructs it as a default provider.api_error. Consequently this helper cannot exercise the newly added branches for context.overflow, provider.overloaded, auth failures, or the other accepted ErrorCode values, while the current provider.api_error test passes accidentally. Propagate a failure event kind that preserves the requested code or bypass that lossy catch.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(acp-server): surface provider errors on session/prompt

1 participant